#include "stdafx.h"
#include "cppflibinc.h"

#include <string.h>

using namespace cppflib;
using namespace cppflib::os;
using namespace cppflib::convert;

static void TestConvert(void)
{
   int a = convert::ToInt32(_S("78900"));
   assert(a == 78900);
   a = convert::ToInt32(_S("-9978900"));
   assert(a == -9978900);
   a = convert::ToInt32(_S("2147483646"));
   assert(a == 2147483646);
   a = convert::ToInt32(_S("2147483647"));
   assert(a == 2147483647);
   a = convert::ToInt32(_S("2147483648"));
   assert(a == 2147483647);
   a = convert::ToInt32(_S("2147483649"));
   assert(a == 2147483647);
   a = convert::ToInt32(_S("-2147483647"));
   assert(a == -2147483647);
   a = convert::ToInt32(_S("-2147483648"));
   assert((u32_t)a == 0x80000000);
   a = convert::ToInt32(_S("-2147483649"));
   assert((u32_t)a == 0x80000000);
   

   a = convert::ToInt32(_S("0xffff"));
   assert(a == 0xffff);
   a = convert::ToInt32(_S("0x7fffffff"));
   assert(a == 0x7fffffff);
   a = convert::ToInt32(_S("0x80000000"));
   assert((u32_t)a == 0x80000000);
   a = convert::ToInt32(_S("0x80000010"));
   assert((u32_t)a == 0x80000010);
   a = convert::ToInt32(_S("0x7ffffffff"));
   assert((u32_t)a == 0xffffffff);

   //// 64 bit ////

   i64_t b = convert::ToInt64(_S("4611686018427387904"));
   assert(b = I64N(4611686018427387904));
   b = convert::ToInt64(_S("9223372036854775807"));
   assert(b = I64N(9223372036854775807));
   b = convert::ToInt64(_S("9223372036854775817"));
   assert(b = I64N(9223372036854775807));
   b = convert::ToInt64(_S("-9223372036854775808"));
   assert((u64_t)b == U64N(0x8000000000000000));
   b = convert::ToInt64(_S("-9223372036854775818"));
   assert((u64_t)b == U64N(0x8000000000000000));

   b = convert::ToInt64(_S("0x7fffffffffffffff"));
   assert(b == I64N(0x7fffffffffffffff));
   b = convert::ToInt64(_S("0x10000000000000000"));
   assert((u64_t)b == U64N(0xffffffffffffffff));
  

   /// single float ///
   float c = convert::ToFloat(_S("14.234"));
   assert(c > 14.233999f && c < 14.234001f);
   c = convert::ToFloat(_S("-14.234"));
   assert(c < -14.233999f && c > -14.234001f);
   c = convert::ToFloat(_S("14.234e+02"));
   assert(c > 1423.3998f && c < 1423.4001f);
   c = convert::ToFloat(_S("14.234e02"));
   assert(c > 1423.3998f && c < 1423.4001f);
   c = convert::ToFloat(_S("14.234e-02"));
   assert(c > 0.14233998f && c < 0.1423401f);
   c = convert::ToFloat(_S("14.234e-2w"));
   assert(c > 0.14233998f && c < 0.1423401f);
   c = convert::ToFloat(_S("14.234e-48"));
   assert(convert::IsZero(c));
   c = convert::ToFloat(_S("14.234E+54"));
   assert(convert::IsInfinity(c));
   c = convert::ToFloat(_S("14"));
   assert(c > 13.9999 && c < 14.0001);
   c = convert::ToFloat(_S("14e3"));
   assert(c > 13999.9 && c < 14000.1);


   /// double float /// 
   double d = convert::ToDouble(_S("2.0234"));
   assert(d > 2.023399999 && d < 2.023400001);
   d = convert::ToDouble(_S("2.0234ab"));
   assert(d > 2.023399999 && d < 2.023400001);
   d = convert::ToDouble(_S("2.0234e"));
   assert(d > 2.023399999 && d < 2.023400001);
   d = convert::ToDouble(_S("2.0234ee"));
   assert(d > 2.023399999 && d < 2.023400001);
   d = convert::ToDouble(_S("2.a0234e"));
   assert(d > 1.99999 && d < 2.00001);
   d = convert::ToDouble(_S("2a.0234"));
   assert(d > 1.99999 && d < 2.00001);
   d = convert::ToDouble(_S("a2.0234"));
   assert(d < 0.0000001);
   d = convert::ToDouble(_S("0.0234"));
   assert(d > 0.02339999 && d < 0.023400001);
   d = convert::ToDouble(_S("0.0000"));
   assert(d < 0.0000001);
   d = convert::ToDouble(_S("-2.0234"));
   assert(d < -2.023399999 && d > -2.023400001);
   d = convert::ToDouble(_S("-2.0234e-333"));
   assert(convert::IsZero(d));
   d = convert::ToDouble(_S("2.0234E+0399"));
   assert(convert::IsInfinity(d));
   d = convert::ToDouble(_S("-2.0234E+0399"));
   assert(convert::IsInfinity(d));
   assert(d < 0);

   assert(convert::ToWUpper(_S('c')) == _S('C'));
   assert(convert::ToWUpper(_S('C')) == _S('C'));
   assert(convert::ToWUpper(_S('1')) == _S('1'));
   assert(convert::ToWLower(_S('C')) == _S('c'));
   assert(convert::ToWLower(_S('c')) == _S('c'));
   assert(convert::ToWLower(_S('1')) == _S('1'));
   assert(convert::ToUpper('c') == 'C');
   assert(convert::ToUpper('C') == 'C');
   assert(convert::ToUpper('1') == '1');
   assert(convert::ToLower('C') == 'c');
   assert(convert::ToLower('c') == 'c');
   assert(convert::ToLower('1') == '1');
    

   CFString s = convert::ToString(-333);
   assert(s.Compare(_S("-333")) == 0);
   s = convert::ToString((u32_t)2234432);
   assert(s.Compare(_S("2234432")) == 0);
   s = convert::ToString((i64_t)I64N(7392993948485));
   assert(s.Compare(_S("7392993948485")) == 0);
   s = convert::ToString((u64_t)U64N(17392993948485));
   assert(s.Compare(_S("17392993948485")) == 0);
}

static void __TestEncodeBase64(u8_t * srcBuf, u8_t * convertedBuf, int convertedLen)
{
   int srcLen = (int)strlen((const char*)srcBuf);
   char *outBuf = NULL;
   int outLen = convertedLen;
   assert(base64::Encode((const u8_t*)srcBuf, srcLen, (u8_t**)&outBuf, (int*)&outLen));
   assert(outLen == convertedLen);
   assert(memcmp(outBuf, convertedBuf, outLen) == 0);
}

static void __TestEncodeBase64_2(u8_t * srcBuf, u8_t * convertedBuf, int convertedLen)
{
   int srcLen = (int)strlen((const char*)srcBuf);
   int outLen = base64::GetEncodeBufferNeed(srcLen);
   char *outBuf = new (FMP_NEWPTR) char[outLen];
   outLen -= 1;
   assert(!base64::Encode((const u8_t*)srcBuf, srcLen, (u8_t**)&outBuf, (int*)&outLen));
}

static void __TestDecodeBase64(u8_t * srcBuf, u8_t * convertedBuf, int convertedLen)
{
   int srcLen = (int)strlen((const char*)srcBuf);
   char *outBuf = NULL;
   int outLen = convertedLen;
   assert(base64::Decode((const u8_t*)srcBuf, srcLen, (u8_t**)&outBuf, (int*)&outLen));
   assert(outLen == convertedLen);
   assert(memcmp(outBuf, convertedBuf, outLen) == 0);
}

static void __TestDecodeBase64_2(u8_t * srcBuf, u8_t * convertedBuf, int convertedLen)
{
   int srcLen = (int)strlen((const char*)srcBuf);
   int outLen = base64::GetDecodeBufferNeed(srcBuf, srcLen);
   char *outBuf = new (FMP_NEWPTR) char[outLen];
   outLen -= 1;
   assert(!base64::Decode((const u8_t*)srcBuf, srcLen, (u8_t**)&outBuf, (int*)&outLen));
}

static void TestBase64(void)
{
   cppmempool::MemPoolWrap localPool;

   __TestEncodeBase64((u8_t*)"748uruf778e8e8wjjdjd", (u8_t*)"NzQ4dXJ1Zjc3OGU4ZTh3ampkamQ=", 28);
   __TestEncodeBase64((u8_t*)"85itkg8erij3", (u8_t*)"ODVpdGtnOGVyaWoz", 16);
   __TestEncodeBase64((u8_t*)"85itkg8erij32", (u8_t*)"ODVpdGtnOGVyaWozMg==", 20);
   __TestEncodeBase64((u8_t*)"85itkg8erij32q", (u8_t*)"ODVpdGtnOGVyaWozMnE=", 20);
   __TestEncodeBase64((u8_t*)"85itkg8erij32qk", (u8_t*)"ODVpdGtnOGVyaWozMnFr", 20);
   __TestEncodeBase64_2((u8_t*)"748uruf778e8e8wjjdjd", (u8_t*)"NzQ4dXJ1Zjc3OGU4ZTh3ampkamQ=", 28);

   __TestDecodeBase64((u8_t*)"ODVpdGtnOGVyaWoz", (u8_t*)"85itkg8erij3", 12);
   __TestDecodeBase64((u8_t*)"ODVpdGtnOGVyaWozMg==", (u8_t*)"85itkg8erij32", 13);
   __TestDecodeBase64((u8_t*)"ODVpdGtnOGVyaWozMnE=", (u8_t*)"85itkg8erij32q", 14);
   __TestDecodeBase64((u8_t*)"ODVpdGtnOGVyaWozMnFr", (u8_t*)"85itkg8erij32qk", 15);
   __TestDecodeBase64_2((u8_t*)"ODVpdGtnOGVyaWozMnFr", (u8_t*)"85itkg8erij32qk", 15);

}

static void TestQuotedPrintable()
{
   cppmempool::MemPoolWrap localPool;

   // encode
   char srcBuf[] = "abc \1\2                                                                     =    9303";
   u8_t * outBuf = NULL;
   int outLen = 0;
   qp::Encode((const u8_t*)srcBuf, (int)strlen(srcBuf), &outBuf, &outLen);
   assert(outLen == 93);
   assert(memcmp(outBuf, "abc =01=02                                                                 =\r\n    =3d    9303", outLen) == 0);

   // decode 
   u8_t * outBuf2 = NULL;
   int outLen2 = 0;
   qp::Decode((const u8_t*)outBuf, outLen, &outBuf2, &outLen2);
   assert(outLen2 == (int)strlen(srcBuf));
   assert(memcmp(outBuf2, srcBuf, outLen2) == 0); 

}

static void TestUrlEncoding()
{
   CFString orgStr(_S("url =&%?+ url"));
   CFString retStr;

   convert::ToUrlEncodedString(orgStr, retStr);
   assert(retStr == _S("url%20%3d%26%25%3f%2b%20url"));

   orgStr = _S("url+%20%3d%26%25%3f%2b%20+url");
   convert::DecodeUrlEncodedString(orgStr, 0, orgStr.GetLength(), retStr);
   assert(retStr == _S("url  =&%?+  url"));

   orgStr = _S("url+%20%3d%26%25%3f%2b%20%rr%$$%qq+url");
   convert::DecodeUrlEncodedString(orgStr, 0, orgStr.GetLength(), retStr);
   assert(retStr == _S("url  =&%?+  url"));
}

void TestDataConversion(void)
{
   debug::Print(_S("Testing data conversion...\n"));
   TestConvert();
   TestBase64();
   TestQuotedPrintable();
   TestUrlEncoding();
}
   